﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Windows.Forms;
using System.Collections;
using System.Diagnostics;
using System.Configuration;
using Microsoft.Win32;
using System.Reflection;
using System.IO;
using System.ComponentModel;
using DVDFilmoteka.Sorting;

namespace DVDFilmoteka
{
    public class GenreItem : IComparable
    {
        public Int32 ID { get; set; }
        public String Name { get; set; }

        public GenreItem(Int32 ID, String Name)
        {
            this.ID = ID;
            this.Name = Name;
        }

        public override string ToString()
        {
            return Name == null ? String.Empty : Name;
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            if (obj is GenreItem)
            {
                return ((GenreItem)obj).ID == this.ID;
            }
            else
            {
                return false;
            }
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        #region IComparable Members

        public int CompareTo(object obj)
        {
            if (obj == null) return 1;
            if (obj is GenreItem)
            {
                return ((GenreItem)obj).Name.CompareTo(this.Name);
            }
            else
            {
                return 1;
            }
        }

        #endregion
    }

    public static class Tools
    {
        // Cache
        private static List<GenreItem> genreList = null;



        public static String CONFIG = Environment.CurrentDirectory + "\\config.xml";
        
        public static List<String> loadDataFromXML(String configFile, String XMLPath)
        {
            List<String> list = new List<string>();

            XmlDocument xml = new XmlDocument();
            xml.Load(configFile);

            XmlElement koren = xml.DocumentElement;
            XmlNodeList seznamUzlu = koren.SelectNodes(XMLPath);

            foreach (XmlNode uzel in seznamUzlu)
            {
                if (uzel.FirstChild != null && uzel.FirstChild.Value != null)
                {
                    list.Add(uzel.FirstChild.Value);
                }
                else
                {
                    list.Add("");
                }
            }

            return list;
        }
        
        /// <summary>
        /// Vrati seznam zanru
        /// </summary>
        /// <returns></returns>
        public static List<GenreItem> getZanrNodeList()
        {
            if (genreList == null)
            {
                List<GenreItem> returnData = new List<GenreItem>();
                foreach (String item in loadDataFromXML(CONFIG, "//root/mzanr/*"))
                {
                    try
                    {
                        String name = item.Substring(item.IndexOf(':') + 1);
                        Int32 id = Int32.Parse(item.Substring(0, item.IndexOf(':')));

                        GenreItem genre = new GenreItem(id, name);                        
                        returnData.Add(genre);
                    }
                    catch { }
                }

                returnData.Add(NoGenre);
                genreList = returnData;
            }

            return genreList;
        }
        public static GenreItem NoGenre = new GenreItem(-1, "Nezařazeno");

        public static GenreItem GetGenreByName(String name, Boolean caseSensitive)
        {
            foreach (GenreItem item in getZanrNodeList())
            {
                String zanrName = item.Name;
                String zanrName2 = name;
                if (!caseSensitive)
                {
                    zanrName = zanrName.ToLower();
                    zanrName2 = name.ToLower();
                }

                if (!String.IsNullOrEmpty(zanrName) && zanrName.Equals(zanrName2)) return item;
            }
            
            return Tools.NoGenre;
        }

        public static GenreItem GetGenreByName(String name)
        {
            return GetGenreByName(name, true);
        }

        public static List<String> getCompresionNodeList()
        {
            return loadDataFromXML(CONFIG, "//root/mkomprese/*");
        }

        // Create a node sorter that implements the IComparer interface.
        public class NodeSorter : IComparer
        {
            // Compare the length of the strings, or the strings
            // themselves, if they are the same length.
            public int Compare(object x, object y)
            {
                TreeNode tx = x as TreeNode;
                TreeNode ty = y as TreeNode;

                if (tx.Tag == null || ty.Tag == null) return 0;

                // If they are the same length, call Compare.
                return string.Compare(tx.Text.ToUpper(), ty.Text.ToUpper());
            }
        }

        /// <summary>
        /// Otevre zadanou stranku v defaultnim webovem prohlizeci
        /// </summary>
        /// <param name="pageAddress"></param>
        public static void openPageInBrowser(String pageAddress)
        {
            String path = Properties.Settings.Default.browserPath;            

            try {
                Process.Start(pageAddress);
            } catch (Exception) {
                try {
                    Process.Start(path, pageAddress);
                } catch (Exception) {
                    MessageBox.Show("Nelze spustit webový prohlížeč " + path + "\nUpravte prosím cestu v konfiguračním souboru aplikace.");
                }
            }
        }

        public static string AssemblyVersion
        {
            get
            {
                return "1.5.1";
            }
        }

        public static string SaveFileVersion
        {
            get
            {
                return "1.2";
            }
        }

        public static string AssemblyName
        {
            get
            {
                return "DVD Filmotéka";
            }
        }

        /// <summary>
        /// Prevede HTML kod na XML
        /// </summary>
        /// <returns></returns>
        public static XmlDocument convertHtmlToXml(String readData)
        {
            String tempDir = Environment.GetEnvironmentVariable("TEMP");
            if (String.IsNullOrEmpty(tempDir))
            {
                tempDir = Environment.GetEnvironmentVariable("TMP");
            }

            if (String.IsNullOrEmpty(tempDir))
            {
                tempDir = Environment.SpecialFolder.ApplicationData.ToString();
            }

            HtmlAgilityPack.HtmlDocument htmlDocument = new HtmlAgilityPack.HtmlDocument();
            htmlDocument.LoadHtml(readData);
            htmlDocument.OptionOutputAsXml = true;            

            htmlDocument.Save(tempDir + "\\temp.xml", Encoding.UTF8);

            XmlDocument document = new XmlDocument();
            using (XmlTextReader tr = new XmlTextReader(tempDir + "\\temp.xml"))
            {
                tr.Namespaces = false;
                document.Load(tr);
            }
            //document.Load(tempDir + "\\temp.xml");
            //File.Delete(tempDir + "\\temp.xml");

            return document;
        }

        /// <summary>
        /// Vyvola udalost synchronizovane
        /// </summary>
        /// <param name="handler"></param>
        /// <param name="args"></param>
        public static void RiseSynchronizedEvent<TEventArgs>(Object sender, EventHandler<TEventArgs> handler, TEventArgs args) where TEventArgs : EventArgs
        {
            if (handler != null)
            {
                foreach (EventHandler<TEventArgs> singleCast in handler.GetInvocationList())
                {
                    ISynchronizeInvoke syncInvoke = singleCast.Target as ISynchronizeInvoke;
                    try
                    {
                        if (syncInvoke != null)
                        {
                            syncInvoke.BeginInvoke(singleCast, new object[] { sender, args });
                            /*if (syncInvoke.InvokeRequired)
                            {
                                // Invokie the event on the main thread
                                syncInvoke.Invoke(singleCast, new object[] { sender, args });
                            }
                            else
                            {
                                singleCast(sender, args);                                
                            }*/
                        }
                        else
                        {
                            // Raise the event
                            throw new Exception("Invocation Target must implements ISynchronizeInvoke interface");
                        }
                    }
                    catch { }
                }
            }
        }

        public class LanguageItem
        {
            public String ShortCode { get; private set; }
            public String Text { get; private set; }

            public LanguageItem(String ShortCode, String Text)
            {
                this.ShortCode = ShortCode;
                this.Text = Text;
            }

            public override string ToString()
            {
                return Text;
            }

            public override bool Equals(object obj)
            {
                if (obj == null || !(obj is LanguageItem)) return false;
                if (this.ShortCode == null) return false;
                if ((obj as LanguageItem).ShortCode == null) return false;

                return this.ShortCode.Equals((obj as LanguageItem).ShortCode);
            }

            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
        }

        public class SorterItem
        {
            public String Text { get; private set; }
            public ESorters Sorter { get; private set; }

            public SorterItem(String Text, ESorters Sorter)
            {
                this.Text = Text;
                this.Sorter = Sorter;
            }

            public override string ToString()
            {
                return this.Text;
            }

            public override bool Equals(object obj)
            {
                return base.Equals(obj);
            }

            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
        }
    }
}
